home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / hplip / base / pkit.py < prev    next >
Text File  |  2009-10-09  |  15KB  |  486 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Stan Dolson
  20. #
  21.  
  22. # Std Lib
  23. import os
  24. import os.path
  25. import sys
  26. import re
  27. import time
  28. import cStringIO
  29. import ConfigParser
  30. import shutil
  31. import stat
  32.  
  33. # Local
  34. from base.logger import *
  35. from base.g import *
  36. from base.codes import *
  37. from base import utils, device
  38.  
  39. # DBus
  40. import dbus
  41. import dbus.service
  42. import gobject
  43.  
  44. import warnings
  45. # Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters
  46. # (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04)
  47. warnings.simplefilter("ignore", DeprecationWarning)
  48.  
  49.  
  50. class AccessDeniedException(dbus.DBusException):
  51.     _dbus_error_name = 'com.hp.hplip.AccessDeniedException'
  52.  
  53. class UnsupportedException(dbus.DBusException):
  54.     _dbus_error_name = 'com.hp.hplip.UnsupportedException'
  55.  
  56. class UsageError(dbus.DBusException):
  57.     _dbus_error_name = 'com.hp.hplip.UsageError'
  58.  
  59.  
  60. POLICY_KIT_ACTION = "com.hp.hplip"
  61. INSTALL_PLUGIN_ACTION = "com.hp.hplip.installplugin"
  62.  
  63.  
  64. def get_service_bus():
  65.     return dbus.SystemBus()
  66.  
  67.  
  68. def get_service(bus=None):
  69.     if not bus:
  70.         bus = get_service_bus()
  71.  
  72.     service = bus.get_object(BackendService.SERVICE_NAME, '/')
  73.     service = dbus.Interface(service, BackendService.INTERFACE_NAME)
  74.     return service
  75.  
  76.  
  77. class PolicyKitAuthentication(object):
  78.     def __init__(self):
  79.         super(PolicyKitAuthentication, self).__init__()
  80.         self.pkit = None
  81.         self.auth = None
  82.  
  83.  
  84.     def is_authorized(self, action_id, pid=None):
  85.         if pid == None:
  86.             pid = os.getpid()
  87.  
  88.         pid = dbus.UInt32(pid)
  89.  
  90.         authorized = self.policy_kit.IsProcessAuthorized(action_id, pid, False)
  91.         log.debug("is_authorized(%s) = %r" % (action_id, authorized))
  92.  
  93.         return (authorized == 'yes')
  94.  
  95.  
  96.     def obtain_authorization(self, action_id, widget=None):
  97.         if self.is_authorized(action_id):
  98.             return True
  99.  
  100.         xid = (widget and widget.get_toplevel().window.xid or 0)
  101.         xid, pid = dbus.UInt32(xid), dbus.UInt32(os.getpid())
  102.  
  103.         granted = self.auth_agent.ObtainAuthorization(action_id, xid, pid)
  104.         log.debug("obtain_authorization(%s) = %r" % (action_id, granted))
  105.  
  106.         return bool(granted)
  107.  
  108.  
  109.     def get_policy_kit(self):
  110.         if self.pkit:
  111.             return self.pkit
  112.  
  113.         service = dbus.SystemBus().get_object('org.freedesktop.PolicyKit', '/')
  114.         self.pkit = dbus.Interface(service, 'org.freedesktop.PolicyKit')
  115.         return self.pkit
  116.  
  117.     policy_kit = property(get_policy_kit)
  118.  
  119.  
  120.     def get_auth_agent(self):
  121.         if self.auth:
  122.             return self.auth
  123.  
  124.         self.auth = dbus.SessionBus().get_object(
  125.             'org.freedesktop.PolicyKit.AuthenticationAgent', '/')
  126.         return self.auth
  127.  
  128.     auth_agent = property(get_auth_agent)
  129.  
  130.  
  131.  
  132. class PolicyKitService(dbus.service.Object):
  133.     def check_permission_v0(self, sender, action=POLICY_KIT_ACTION):
  134.         if not sender:
  135.             log.error("Session not authorized by PolicyKit")
  136.             raise AccessDeniedException('Session not authorized by PolicyKit')
  137.  
  138.         try:
  139.             policy_auth = PolicyKitAuthentication()
  140.             bus = dbus.SystemBus()
  141.  
  142.             dbus_object = bus.get_object('org.freedesktop.DBus', '/')
  143.             dbus_object = dbus.Interface(dbus_object, 'org.freedesktop.DBus')
  144.  
  145.             pid = dbus.UInt32(dbus_object.GetConnectionUnixProcessID(sender))
  146.  
  147.             granted = policy_auth.is_authorized(action, pid)
  148.             if not granted:
  149.                 log.error("Process not authorized by PolicyKit")
  150.                 raise AccessDeniedException('Process not authorized by PolicyKit')
  151.  
  152.             granted = policy_auth.policy_kit.IsSystemBusNameAuthorized(action,
  153.                                                                        sender,
  154.                                                                        False)
  155.             if granted != 'yes':
  156.                 log.error("Session not authorized by PolicyKit version 0")
  157.                 raise AccessDeniedException('Session not authorized by PolicyKit')
  158.  
  159.         except AccessDeniedException:
  160.             log.warning("AccessDeniedException")
  161.             raise
  162.  
  163.         except dbus.DBusException, ex:
  164.             log.warning("AccessDeniedException %r", ex)
  165.             raise AccessDeniedException(ex.message)
  166.  
  167.  
  168.     def check_permission_v1(self, sender, connection, action=POLICY_KIT_ACTION):
  169.         if not sender or not connection:
  170.             log.error("Session not authorized by PolicyKit")
  171.             raise AccessDeniedException('Session not authorized by PolicyKit')
  172.  
  173.         system_bus = dbus.SystemBus()
  174.         obj = system_bus.get_object("org.freedesktop.PolicyKit1",
  175.                                     "/org/freedesktop/PolicyKit1/Authority",
  176.                                     "org.freedesktop.PolicyKit1.Authority")
  177.         policy_kit = dbus.Interface(obj, "org.freedesktop.PolicyKit1.Authority")
  178.         info = dbus.Interface(connection.get_object("org.freedesktop.DBus",
  179.                                                     "/org/freedesktop/DBus/Bus",
  180.                                                     False),
  181.                               "org.freedesktop.DBus")
  182.         pid = info.GetConnectionUnixProcessID(sender)
  183.         
  184.         subject = (
  185.             'unix-process',
  186.             { 'pid' : dbus.UInt32(pid, variant_level = 1) }
  187.         )
  188.         details = { '' : '' }
  189.         flags = dbus.UInt32(1)         # AllowUserInteraction = 0x00000001
  190.         cancel_id = ''
  191.  
  192.         (ok, notused, details) = \
  193.             policy_kit.CheckAuthorization(subject,
  194.                                           action,
  195.                                           details,
  196.                                           flags,
  197.                                           cancel_id)
  198.         if not ok:
  199.             log.error("Session not authorized by PolicyKit version 1")
  200.  
  201.         return ok
  202.  
  203.  
  204. class BackendService(PolicyKitService):
  205.     INTERFACE_NAME = 'com.hp.hplip'
  206.     SERVICE_NAME   = 'com.hp.hplip'
  207.     LOGFILE_NAME   = '/tmp/hp-pkservice.log'
  208.  
  209.     def __init__(self, connection=None, path='/', logfile=LOGFILE_NAME):
  210.         if connection is None:
  211.             connection = get_service_bus()
  212.  
  213.         super(BackendService, self).__init__(connection, path)
  214.  
  215.         self.name = dbus.service.BusName(self.SERVICE_NAME, connection)
  216.         self.loop = gobject.MainLoop()
  217.         self.version = 0
  218.  
  219.         log.set_logfile("%s.%d" % (logfile, os.getpid()))
  220.         log.set_level("debug")
  221.  
  222.     def run(self, version=None):
  223.         if version is None:
  224.             version = policykit_version()
  225.             if version is None:
  226.                 log.error("Unable to determine installed PolicyKit version")
  227.                 return
  228.  
  229.         self.version = version
  230.         log.set_where(Logger.LOG_TO_CONSOLE_AND_FILE)
  231.         log.debug("Starting back-end service loop (version %d)" % version)
  232.  
  233.         self.loop.run()
  234.  
  235.  
  236.     @dbus.service.method(dbus_interface=INTERFACE_NAME,
  237.                             in_signature='s', out_signature='b',
  238.                             sender_keyword='sender',
  239.                             connection_keyword='connection')
  240.     def installPlugin(self, src_dir, sender=None, connection=None):
  241.         if self.version == 0:
  242.             try:
  243.                 self.check_permission_v0(sender, INSTALL_PLUGIN_ACTION)
  244.             except AccessDeniedException, e:
  245.                 return False
  246.  
  247.         elif self.version == 1:
  248.             if not self.check_permission_v1(sender,
  249.                                             connection,
  250.                                             INSTALL_PLUGIN_ACTION):
  251.                 return False
  252.  
  253.         else:
  254.             log.error("installPlugin: invalid PolicyKit version %d" % self.version)
  255.             return False
  256.  
  257.         log.debug("installPlugin: installing from '%s'" % src_dir)
  258.  
  259.         if not copyPluginFiles(src_dir):
  260.             log.error("Plugin installation failed")
  261.             return False
  262.  
  263.         return True
  264.  
  265.  
  266.     @dbus.service.method(dbus_interface=INTERFACE_NAME,
  267.                             in_signature='', out_signature='b',
  268.                             sender_keyword='sender',
  269.                             connection_keyword='connection')
  270.     def shutdown(self, sender=None, connection=None):
  271.         log.debug("Stopping backend service")
  272.         self.loop.quit()
  273.  
  274.         return True
  275.  
  276.  
  277.  
  278. class PolicyKit(object):
  279.     def __init__(self, version=None):
  280.         if version is None:
  281.             version = policykit_version()
  282.             if version is None:
  283.                 log.error("Unable to determine installed PolicyKit version")
  284.                 return
  285.  
  286.         self.bus = dbus.SystemBus()
  287.         self.obj = self.bus.get_object(POLICY_KIT_ACTION, "/")
  288.         self.iface = dbus.Interface(self.obj, dbus_interface=POLICY_KIT_ACTION)
  289.         self.version = version
  290.  
  291.     def installPlugin(self, src_dir):
  292.         if self.version == 0:
  293.             auth = PolicyKitAuthentication()
  294.             if not auth.is_authorized(INSTALL_PLUGIN_ACTION):
  295.                 if not auth.obtain_authorization(INSTALL_PLUGIN_ACTION):
  296.                     return None
  297.  
  298.         try:
  299.             ok = self.iface.installPlugin(src_dir)
  300.             return ok
  301.         except dbus.DBusException, e:
  302.             log.debug("installPlugin: %s" % str(e))
  303.             return False
  304.  
  305.  
  306.     def shutdown(self):
  307.         if self.version == 0:
  308.             auth = PolicyKitAuthentication()
  309.             if not auth.is_authorized(INSTALL_PLUGIN_ACTION):
  310.                 if not auth.obtain_authorization(INSTALL_PLUGIN_ACTION):
  311.                     return None
  312.  
  313.         try:
  314.             ok = self.iface.shutdown()
  315.             return ok
  316.         except dbus.DBusException, e:
  317.             log.debug("shutdown: %s" % str(e))
  318.             return False
  319.  
  320.  
  321.  
  322. def copyPluginFiles(src_dir):
  323.     os.chdir(src_dir)
  324.  
  325.     plugin_spec = ConfigBase("plugin.spec")
  326.     products = plugin_spec.keys("products")
  327.  
  328.     BITNESS = utils.getBitness()
  329.     ENDIAN = utils.getEndian()
  330.     PPDDIR = sys_conf.get('dirs', 'ppd')
  331.     DRVDIR = sys_conf.get('dirs', 'drv')
  332.     HOMEDIR = sys_conf.get('dirs', 'home')
  333.     DOCDIR = sys_conf.get('dirs', 'doc')
  334.     CUPSBACKENDDIR = sys_conf.get('dirs', 'cupsbackend')
  335.     CUPSFILTERDIR = sys_conf.get('dirs', 'cupsfilter')
  336.     RULESDIR = '/etc/udev/rules.d'
  337.  
  338.     processor = utils.getProcessor()
  339.     if processor == 'power_machintosh':
  340.         ARCH = 'ppc'
  341.     else:
  342.         ARCH = 'x86_%d' % BITNESS
  343.  
  344.     if BITNESS == 64:
  345.         SANELIBDIR = '/usr/lib64/sane'
  346.         LIBDIR = '/usr/lib64'
  347.     else:
  348.         SANELIBDIR = '/usr/lib/sane'
  349.         LIBDIR = '/usr/lib'
  350.  
  351.     copies = []
  352.  
  353.     for PRODUCT in products:
  354.         MODEL = PRODUCT.replace('hp-', '').replace('hp_', '')
  355.         for s in plugin_spec.get("products", PRODUCT).split(','):
  356.  
  357.             if not plugin_spec.has_section(s):
  358.                 log.error("Missing section [%s]" % s)
  359.                 return False
  360.  
  361.             src = plugin_spec.get(s, 'src', '')
  362.             trg = plugin_spec.get(s, 'trg', '')
  363.             link = plugin_spec.get(s, 'link', '')
  364.  
  365.             if not src:
  366.                 log.error("Missing 'src=' value in section [%s]" % s)
  367.                 return False
  368.  
  369.             if not trg:
  370.                 log.error("Missing 'trg=' value in section [%s]" % s)
  371.                 return False
  372.  
  373.             src = os.path.basename(utils.cat(src))
  374.             trg = utils.cat(trg)
  375.  
  376.             if link:
  377.                 link = utils.cat(link)
  378.  
  379.             copies.append((src, trg, link))
  380.  
  381.     copies = utils.uniqueList(copies)
  382.     copies.sort()
  383.  
  384.     os.umask(0)
  385.  
  386.     for src, trg, link in copies:
  387.  
  388.         if not os.path.exists(src):
  389.             log.debug("Source file %s does not exist. Skipping." % src)
  390.             continue
  391.  
  392.         if os.path.exists(trg):
  393.             log.debug("Target file %s already exists. Replacing." % trg)
  394.             os.remove(trg)
  395.  
  396.         trg_dir = os.path.dirname(trg)
  397.  
  398.         if not os.path.exists(trg_dir):
  399.             log.debug("Target directory %s does not exist. Creating." % trg_dir)
  400.             os.makedirs(trg_dir, 0755)
  401.  
  402.         if not os.path.isdir(trg_dir):
  403.             log.error("Target directory %s exists but is not a directory. Skipping." % trg_dir)
  404.             continue
  405.  
  406.         try:
  407.             shutil.copyfile(src, trg)
  408.         except (IOError, OSError), e:
  409.             log.error("File copy failed: %s" % e.strerror)
  410.             continue
  411.  
  412.         else:
  413.             if not os.path.exists(trg):
  414.                 log.error("Target file %s does not exist. File copy failed." % trg)
  415.                 continue
  416.             else:
  417.                 os.chmod(trg, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH)
  418.  
  419.             if link:
  420.                 if os.path.exists(link):
  421.                     log.debug("Symlink already exists. Replacing.")
  422.                     os.remove(link)
  423.  
  424.                 log.debug("Creating symlink %s (link) to file %s (target)..." %
  425.                     (link, trg))
  426.  
  427.                 try:
  428.                     os.symlink(trg, link)
  429.                 except (OSError, IOError), e:
  430.                     log.debug("Unable to create symlink: %s" % e.strerror)
  431.                     pass
  432.  
  433.     log.debug("Updating hplip.conf - installed = 1")
  434.     sys_state.set('plugin', "installed", '1')
  435.     log.debug("Updating hplip.conf - eula = 1")
  436.     sys_state.set('plugin', "eula", '1')
  437.  
  438.     return True
  439.  
  440.  
  441. def run_plugin_command(required=True, plugin_reason=PLUGIN_REASON_NONE):
  442.     su_sudo = None
  443.     need_sudo = True
  444.  
  445.     if utils.to_bool(sys_conf.get('configure', 'policy-kit')):
  446.         try:
  447.             obj = PolicyKit()
  448.             su_sudo = "%s"
  449.             need_sudo = False
  450.             log.debug("Using PolicyKit for authentication")
  451.         except dbus.DBusException, ex:
  452.             log.error("PolicyKit NOT installed when configured for use")
  453.  
  454.     if os.geteuid() == 0:
  455.         su_sudo = "%s"
  456.         need_sudo = False
  457.  
  458.     if need_sudo:
  459.         su_sudo = utils.su_sudo()
  460.         if su_sudo is None:
  461.             log.error("Unable to find a suitable sudo command to run 'hp-plugin'")
  462.             return (False, False)
  463.  
  464.     req = '--required'
  465.     if not required:
  466.         req = '--optional'
  467.  
  468.     if utils.which("hp-plugin"):
  469.         cmd = su_sudo % ("hp-plugin -u %s --reason %s" % (req, plugin_reason))
  470.     else:
  471.         cmd = su_sudo % ("python ./plugin.py -u %s --reason %s" % (req, plugin_reason))
  472.  
  473.     log.debug("%s" % cmd)
  474.     status, output = utils.run(cmd, log_output=True, password_func=None, timeout=1)
  475.  
  476.     return (status == 0, True)
  477.  
  478.  
  479. def policykit_version():
  480.     if os.path.isdir("/usr/share/polkit-1"):
  481.         return 1
  482.     elif os.path.isdir("/usr/share/PolicyKit"):
  483.         return 0
  484.     else:
  485.         return None
  486.